package com.wordplat.quickstart.xutils.common.util;

import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * URLUtil
 *
 * @since 2021-05-08
 */
public final class URLUtil {
    private static final Pattern CONTENT_DISPOSITION_PATTERN =
            Pattern.compile("attachment;\\s*filename\\s*=\\s*(\"?)([^\"]*)\\1\\s*$", Pattern.CASE_INSENSITIVE);

    private static final String LOGTAG = "webkit";
    private static final boolean TRACE = false;
    /**
     * to refer to bar.png under your package's asset/foo/ directory, use
     */
    private static final String ASSET_BASE = "file:///ohos_asset/";
    /**
     * // to refer to bar.png under your package's res/drawable/ directory, use
     * // "file:///ohos_asset/drawable/bar.png". Use "drawable" to refer to
     * // "drawable-hdpi" directory as well.
     */
    private static final String RESOURCE_BASE = "file:///ohos_asset/";
    private static final String FILE_BASE = "file:";
    private static final String PROXY_BASE = "file:///cookieless_proxy/";
    private static final String CONTENT_BASE = "content:";

    private URLUtil() {
    }

    /**
     * composeSearchUrl
     *
     * @param inQuery
     * @param template
     * @param queryPlaceHolder
     * @return String
     */
    public static String composeSearchUrl(String inQuery, String template,
                                          String queryPlaceHolder) {
        int placeHolderIndex = template.indexOf(queryPlaceHolder);
        if (placeHolderIndex < 0) {
            return null;
        }

        String query;
        StringBuilder buffer = new StringBuilder();
        buffer.append(template.substring(0, placeHolderIndex));

        try {
            query = java.net.URLEncoder.encode(inQuery, "utf-8");
            buffer.append(query);
        } catch (UnsupportedEncodingException ex) {
            return null;
        }

        buffer.append(template.substring(
                placeHolderIndex + queryPlaceHolder.length()));

        return buffer.toString();
    }

    /**
     * decode
     *
     * @param url
     * @return byte
     * @throws IllegalArgumentException
     */
    public static byte[] decode(byte[] url) throws IllegalArgumentException {
        if (url.length == 0) {
            return new byte[0];
        }

        // Create a new byte array with the same length to ensure capacity
        byte[] tempData = new byte[url.length];

        int tempCount = 0;
        for (int i = 0; i < url.length; i++) {
            byte b = url[i];
            if (b == '%') {
                if (url.length - i > 2) {
                    b = (byte) (parseHex(url[i + 1]) * 16
                            + parseHex(url[i + 2]));
                    i += 2;
                } else {
                    throw new IllegalArgumentException("Invalid format");
                }
            }
            tempData[tempCount++] = b;
        }
        byte[] retData = new byte[tempCount];
        System.arraycopy(tempData, 0, retData, 0, tempCount);
        return retData;
    }

    /**
     * verifyURLEncoding
     *
     * @param url
     * @return boolean
     */
    static boolean verifyURLEncoding(String url) {
        int count = url.length();
        if (count == 0) {
            return false;
        }

        int index = url.indexOf('%');
        while (index >= 0 && index < count) {
            if (index < count - 2) {
                try {
                    parseHex((byte) url.charAt(++index));
                    parseHex((byte) url.charAt(++index));
                } catch (IllegalArgumentException e) {
                    return false;
                }
            } else {
                return false;
            }
            index = url.indexOf('%', index + 1);
        }
        return true;
    }

    private static int parseHex(byte b) {
        if (b >= '0' && b <= '9') {
            return (b - '0');
        }
        if (b >= 'A' && b <= 'F') {
            return (b - 'A' + 10);
        }
        if (b >= 'a' && b <= 'f') {
            return (b - 'a' + 10);
        }

        throw new IllegalArgumentException("Invalid hex char '" + b + "'");
    }

    /**
     * isAssetUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isAssetUrl(String url) {
        return (null != url) && url.startsWith(ASSET_BASE);
    }

    /**
     * isResourceUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isResourceUrl(String url) {
        return (null != url) && url.startsWith(RESOURCE_BASE);
    }

    /**
     * isCookielessProxyUrl
     *
     * @param url
     * @return boolean
     */
    @Deprecated
    public static boolean isCookielessProxyUrl(String url) {
        return (null != url) && url.startsWith(PROXY_BASE);
    }

    /**
     * isFileUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isFileUrl(String url) {
        return (null != url) && (url.startsWith(FILE_BASE)
                && !url.startsWith(ASSET_BASE)
                && !url.startsWith(PROXY_BASE));
    }

    /**
     * isAboutUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isAboutUrl(String url) {
        return (null != url) && url.startsWith("about:");
    }

    /**
     * isDataUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isDataUrl(String url) {
        return (null != url) && url.startsWith("data:");
    }

    /**
     * isJavaScriptUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isJavaScriptUrl(String url) {
        return (null != url) && url.startsWith("javascript:");
    }

    /**
     * isHttpUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isHttpUrl(String url) {
        return (null != url)
                && (url.length() > 6)
                && url.substring(0, 7).equalsIgnoreCase("http://");
    }

    /**
     * isHttpsUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isHttpsUrl(String url) {
        return (null != url)
                && (url.length() > 7)
                && url.substring(0, 8).equalsIgnoreCase("https://");
    }

    /**
     * isNetworkUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isNetworkUrl(String url) {
        if (url == null || url.length() == 0) {
            return false;
        }
        return isHttpUrl(url) || isHttpsUrl(url);
    }

    /**
     * isContentUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isContentUrl(String url) {
        return (null != url) && url.startsWith(CONTENT_BASE);
    }

    /**
     * isValidUrl
     *
     * @param url
     * @return boolean
     */
    public static boolean isValidUrl(String url) {
        if (url == null || url.length() == 0) {
            return false;
        }

        return (isAssetUrl(url)
                || isResourceUrl(url)
                || isFileUrl(url)
                || isAboutUrl(url)
                || isHttpUrl(url)
                || isHttpsUrl(url)
                || isJavaScriptUrl(url)
                || isContentUrl(url));
    }

    /**
     * stripAnchor
     *
     * @param url
     * @return String
     */
    public static String stripAnchor(String url) {
        int anchorIndex = url.indexOf('#');
        if (anchorIndex != -1) {
            return url.substring(0, anchorIndex);
        }
        return url;
    }


    /**
     * parseContentDisposition
     *
     * @param contentDisposition
     * @return String
     */
    static String parseContentDisposition(String contentDisposition) {
        try {
            Matcher matcher = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
            if (matcher.find()) {
                return matcher.group(2);
            }
        } catch (IllegalStateException ex) {
            // This function is defined as returning null when it can't parse the header
            LogUtil.e("error:" + ex);
        }
        return null;
    }
}
